/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "ScrollBar.h"
#include <xml/Stream.h>

namespace liba
{
namespace lib2d
{
namespace gui
{

ScrollBar::ScrollBar( Object * parent )
:	Object( parent ),
	page_size( 0.5 ),
	step( 12 ),
	min( 0 ),
	max( 100 ),
	pos( 0 )
{
	top = new scrollbar::TopButton( this );
	bottom = new scrollbar::BottomButton( this );
	center = new scrollbar::CenterButton( this );

	view = new view::ScrollBar( this );
	AutoPtr< resource::Resource > res = resource::Manager::create_resource( "scrollbar.xml" );
	xml::StreamResource( res ).load( &xml::Root( view, "ScrollBarData" ) );

	layout();
}

void ScrollBar::layout()
{
	window_rect = get_parent()->get_window_rect();
	window_rect.y = 0;
	window_rect.x = window_rect.width - view->get_width();
	window_rect.width = view->get_width();
	//	parent->window_rect.width -= 20;

	top->layout();
	bottom->layout();

	Rect rect = get_center_button_area();
	double center_button_height = rect.height * page_size;
	double center_button_y = rect.y;
	if( max - min )
		center_button_y = rect.y + (rect.height - center_button_height)*(pos - min)/(max - min);

	center->layout( center_button_y, center_button_height );
}

void ScrollBar::update_position()
{
	Rect rect = get_center_button_area();
	if( max - min )
		pos = min + (max - min)*(center->get_window_rect().y - rect.y)/(rect.height - center->get_window_rect().height);
	else
		pos = 0;
}

void ScrollBar::on_button_down( const Vector2 & point, const Atom & button_name )
{
	Rect top_rect = top->get_window_rect();
	Rect bottom_rect = bottom->get_window_rect();
	Rect center_rect = center->get_window_rect();
	if( !top_rect.is_intersects( point ) &&
		!bottom_rect.is_intersects( point ) &&
		!center_rect.is_intersects( point ) )
	{
		if( point.y() < center_rect.y )
			set_position( pos - center_rect.height * page_size );
		else
			set_position( pos + center_rect.height * page_size );
	}

	Object::on_button_down( point, button_name );		
}

bool ScrollBar::on_attribute( xml::Provider * prov, const std::string & name, const std::string & value )
{
	return false;
}

bool ScrollBar::on_node( xml::Provider * prov, const std::string & name )
{
	return false;
}

namespace scrollbar
{

TopButton::TopButton( ScrollBar * parent )
	:	Button( parent ),
	next_event_time( 0 ),
	scroll_bar( parent )
{}

void TopButton::on_button_down( const Vector2 & point, const Atom & button_name )
{
	scroll_bar->set_position( scroll_bar->get_position() - scroll_bar->get_step() );
	next_event_time = 0.3;
	Button::on_button_down( point, button_name );
}

void TopButton::life_cycle( double delta_time )
{
	if( !is_pressed() )
		return;
	if( next_event_time > 0 )
	{
		next_event_time -= delta_time;
		if( next_event_time <= 0 )
		{
			scroll_bar->set_position( scroll_bar->get_position() - scroll_bar->get_step() );
			next_event_time = 0.1;
		}
	}
	Button::life_cycle( delta_time );
}

BottomButton::BottomButton( ScrollBar * parent )
	:	Button( parent ),
	next_event_time( 0 ),
	scroll_bar( parent )
{}

void BottomButton::on_button_down( const Vector2 & point, const Atom & button_name )
{
	next_event_time = 0.3;
	scroll_bar->set_position( scroll_bar->get_position() + scroll_bar->get_step() );
	Button::on_button_down( point, button_name );
}

void BottomButton::life_cycle( double delta_time )
{
	if( !is_pressed() )
		return;
	if( next_event_time > 0 )
	{
		next_event_time -= delta_time;
		if( next_event_time <= 0 )
		{
			scroll_bar->set_position( scroll_bar->get_position() + scroll_bar->get_step() );
			next_event_time = 0.1;
		}
	}
	Button::life_cycle( delta_time );
}

void CenterButton::on_mouse_move_outside( const Vector2 & point )
{
	if( mouse_pressed )
	{
		window_rect.y += point.y() - track_mouse_point.y();
		Rect rect = scroll_bar->get_center_button_area();
		if( window_rect.y < rect.y )
			window_rect.y = rect.y;
		if( window_rect.y + window_rect.height > rect.y + rect.height )
			window_rect.y = rect.y + rect.height - window_rect.height;
		//TODO send action
		scroll_bar->update_position();
	}
}

void CenterButton::on_mouse_out()
{
	if( mouse_pressed )
		return Object::on_mouse_out();

	Button::on_mouse_out();
}

void CenterButton::on_button_up( const Vector2 & point, const Atom & button_name )
{
	Rect wr( window_rect );
	wr.shift( Vector2( -wr.get_coord() ) );
	if( !wr.is_intersects( point ) )
		mouse_over = false;

	Button::on_button_up( point, button_name );
}

void CenterButton::on_mouse_move( const Vector2 & point )
{
	Button::on_mouse_move( point );
	CenterButton::on_mouse_move_outside( point );
}

void CenterButton::on_button_down( const Vector2 & point, const Atom & button_name )
{
	track_mouse_point = point;
	Button::on_button_down( point, button_name );
}

} //namespace scrollbar

} //namespace gui
} //namespace lib2d
} //namespace liba

